/*************************************************************************
	> File Name: tsd_once.c
	> Author: 
	> Mail: 
	> Created Time: 2015年01月20日 星期二 22时35分11秒
 ************************************************************************/

#include<pthread.h>
#include"errors.h"

typedef struct tsd_tag{
    pthread_t   thread_id;
    char        *string;
} tsd_t;

pthread_key_t   tsd_key;
pthread_once_t  key_once = PTHREAD_ONCE_INIT;

void once_routine(void){
    int status;

    printf("initializing key\n");
    status = pthread_key_create(&tsd_key,NULL);
    if(status) err_abort(status,"Create key");
}

void *thread_routine(void* arg){
    tsd_t *value;
    int status;

    status = pthread_once(&key_once,once_routine);
    if(status) err_abort(status,"Once init");
    
    value = (tsd_t *)malloc(sizeof(tsd_t));
    if(NULL == value) errno_abort("allocate key value");

    status = pthread_setspecific(tsd_key,value);
    if(status) err_abort(status,"set tsd");

    printf("%s set tsd value %p\n",(char *)arg,value);

    value->thread_id = pthread_self();
    value->string = (char *)arg;
    value = (tsd_t*) pthread_getspecific(tsd_key);
    printf("%s starting .... \n",value->string);
    sleep(2);
    value = (tsd_t *) pthread_getspecific(tsd_key);
    printf("%s done .... \n",value->string);
    return NULL;
}

int main(int argc,char *argv[]){
    pthread_t t1,t2;
    int status;

    status = pthread_create(&t1,NULL,thread_routine,"Thread 1");
    if(status) err_abort(status,"Create thread 1 ");

    status = pthread_create(&t2,NULL,thread_routine,"Thread 2");
    if(status) err_abort(status,"Create thread 2 ");

    pthread_exit(NULL);

    return 0;
}
